package fortunata.jspwikiplugins.vpoet;

import com.ecyrd.jspwiki.WikiContext;
import com.ecyrd.jspwiki.plugin.PluginException;
import com.ecyrd.jspwiki.plugin.WikiPlugin;
import fortunata.FortunataPlugin;
import fortunata.fswapps.vpoet.Vpoet;
import org.apache.log4j.Logger;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Map;


/**
 * This plugin reads a form intended to be used by Visualization Providers (VPs).
 * The form allow VPs to insert visualizations in VPOET
 */
public class AddVisualization extends FortunataPlugin implements WikiPlugin {
    private static Logger log = Logger.getLogger( AddVisualization.class );
    public static String nl = System.getProperty("line.separator");
    public static String wnl = "\\\\" + nl;
    public static String vpPrefix = "vp";
//    String designID, elem, providerID,
//           csscode, jscode, htmlcode,
//           designType,
//           selStyle1, selColour1, selBack1,
//           selStyle2, selColour2, selBack2,
//           userSTD, userRVS, colorBlind,
//           policySize,
//           policyResize;
    private char[] pairedMonogamicSymbols = {'\'', '"'};
    private char[][] pairedBigamicSymbols = {
                                             {'{', '}'},
                                             {'[', ']'},
                                             {'<', '>'},
                                             {'(', ')'},
                                            };
    Vpoet vpoet;

    public String execute (WikiContext context, Map parameterMap) throws PluginException {
       vpoet = new Vpoet();
       try{
            String designID     = FormManager.getFieldNoEmplyValue("designID", parameterMap, "design ID");
            String elem         = FormManager.getFieldNoEmplyValue("elem",     parameterMap, "element");
            String providerID   = FormManager.getFieldNoEmplyValue("id",       parameterMap, "your ID");
            String csscode      = FormManager.getFieldValue         ("csscode",  parameterMap);
            String jscode       = FormManager.getFieldValue         ("jscode",  parameterMap);
            String htmlcode     = FormManager.getFieldValue         ("htmlcode",  parameterMap);
            String designType   = FormManager.getToggleFieldValue   ("designType",  parameterMap);
            //System.out.println("designType=" + designType);
            String selStyle1    = FormManager.getFieldValue         ("selStyle1",  parameterMap);
            String selColour1   = FormManager.getFieldValue         ("selColour1",  parameterMap);
            String selBack1     = FormManager.getFieldValue         ("selBack1",  parameterMap);
            String selStyle2    = FormManager.getFieldValue         ("selStyle2",  parameterMap);
            String selColour2   = FormManager.getFieldValue         ("selColour2",  parameterMap);
            String selBack2     = FormManager.getFieldValue         ("selBack2",  parameterMap);
            String userSTD      = FormManager.getToggleFieldValue   ("userSTD",  parameterMap);
            String userRVS      = FormManager.getToggleFieldValue   ("userRVS",  parameterMap);
            String colorBlind   = FormManager.getToggleFieldValue   ("colorBlind",  parameterMap);
            String policySize   = FormManager.getFieldValue         ("policySize",  parameterMap);
            String policyResize = FormManager.getFieldValue         ("policyResize",  parameterMap);

            vpoet.addFormData(designID, elem, providerID,
                              csscode, jscode, htmlcode,
                              designType,
                              selStyle1, selColour1, selBack1,
                              selStyle2, selColour2, selBack2,
                              userSTD, userRVS, colorBlind,
                              policySize,
                              policyResize);
            //Validate values
            validateInsertedCode(htmlcode, csscode, jscode);
            //Ensures exists the ontologies-list page
            createWikiPageListIfNeeded(context, Vpoet.listWikiPageName);
            //Writes data to semantic model
            vpoet.writeSemanticData(context);

            //Show results message
            String
            wikiTextMessage = "Information added to [" + Vpoet.listWikiPageName + "] by " + context.getCurrentUser().getName();
            return renderWikiText(context, wikiTextMessage, FortunataPlugin.MSG_TYPE_OK);
        } catch(PluginException e){
            //Shows a nice red alert with the message.
            throw new PluginException(renderWikiText(context, e.getMessage()));
        }

    }
    private void validateInsertedCode(String htmlcode, String csscode, String jscode) throws PluginException{
        boolean  htmlOK,
                 cssOK,
                 jsOK;
        try {
           htmlOK = hasPairedSymbols(htmlcode);
        }catch (PluginException e){
           throw new PluginException("Code in HTML section is probably wrong. " + e.getMessage());
        }
        try {
           cssOK = hasPairedSymbols(csscode);
        }catch (PluginException e){
           throw new PluginException("Code in CSS section is probably wrong. " + e.getMessage());
        }
        try {
           jsOK = hasPairedSymbols(jscode);
        }catch (PluginException e){
           throw new PluginException("Code in Javascript section is probably wrong. " + e.getMessage());
        }
    }
    private boolean hasPairedSymbols(String code) throws PluginException{
        int i;
        int j;
        boolean res = true;
        int[] counterMonogamic = new int [pairedMonogamicSymbols.length];
        for (i = 0; i < pairedMonogamicSymbols.length; i++){
           for (j = 0; j < code.length(); j++){
               if (code.charAt(j) == pairedMonogamicSymbols[i]){
                   counterMonogamic[i]++;
               }
           }
        }
        for (i = 0; i < counterMonogamic.length; i++){
            if (counterMonogamic[i] % 2 == 1){ //If a non paired number
                res = false;
                throw new PluginException("The number of characters " + pairedMonogamicSymbols[i] + " do not match. Check your code.");
            }
        }
        int[][] counterBigamic = new int [pairedBigamicSymbols.length][2];
        for (i = 0; i < pairedBigamicSymbols.length; i++){
           for (j = 0; j < code.length(); j++){
               if (code.charAt(j) == pairedBigamicSymbols[i][0]){
                   counterBigamic[i][0]++;
               }
               if (code.charAt(j) == pairedBigamicSymbols[i][1]){
                   counterBigamic[i][1]++;
               }
           }
        }
        for (i = 0; i < counterBigamic.length; i++){
            if (counterBigamic[i][0] != counterBigamic[i][1]){ //If a non balanced number
                res = false;
                throw new PluginException("The number of characters " + pairedBigamicSymbols[i][0] +
                                          " and " +pairedBigamicSymbols[i][1] + " are different. Check your code.");
            }
        }
        return res;
    }
    private void createWikiPageListIfNeeded(WikiContext context, String wikiPageName) throws PluginException{
         String wikiPageFullFileName = WikiPageName2FullFileName(context, wikiPageName);
         File file = new File(wikiPageFullFileName);
         if (file.exists() == false){
             try {
                FileOutputStream fos = new FileOutputStream(file);
                PrintStream ps = new PrintStream(fos);
                ps.print(
                    "[{Image src='"+ ImageSemData +"' align='center' link='"+
                            getURLBase(context)+ vpoet.getIndividualsFileName() + "'}]" +
                    "[{FormSet form='VisualizationsForm'}]\n" +
                    "[{FormOpen form='VisualizationsForm'}]\n" +
                    "[{FormOutput form='VisualizationsForm' handler='fortunata.jspwikiplugins.vpoet.OnListOperation'}]\n" +
                    Vpoet.pluginGenerateListString + "\n" +
                     "[{FormClose}]");
                ps.close();
                fos.close();
             }catch(IOException e){
                log.error("Can not create wiki page " + wikiPageName);
                throw new PluginException("Can not create " + wikiPageName);
             }
         }
     }

      public static void main (String[] args){
          String codeWrong1 = "testFunc(\"arg1\", \"arg2\", \"arg3 )"; //Missing "
          String codeWrong2 = "testFunc('arg1', 'arg2', 'arg3 )"; //Missing '
          String codeWrong3 = "what ever {{ other }"; //Missing }
          String codeWrong4 = "what ever [[ other ]"; //Missing ]
          String codeOK1 = "testFunc(\"arg1\", \"arg2\", \"arg3\" )"; //OK "
          String codeOK2 = "testFunc('arg1', 'arg2', 'arg3' )"; //OK '
          String codeOK3 = "what ever {{ other }and }"; //OK }
          String codeOK4 = "what ever [[ other ]and ]"; //OK ]
          String codeComplex1 = "{{}[b[]a]}"; //OK
          String codeComplex2 = "{\"{}[b\"[]a']'}"; //OK
          String codeComplex3 = "{<\"(){}<[b\"[]a']'}>>"; //OK
          String codeComplex4 = "{<\"(){}<[b\"[]a']'}>"; // Missing >
          String[] code = {codeWrong1, codeWrong2, codeWrong3, codeWrong4,
                           codeOK1, codeOK2, codeOK3, codeOK4,
                           codeComplex1, codeComplex2, codeComplex3, codeComplex4};
          for (int i = 0; i < code.length; i++){
              try {
                 AddVisualization av = new AddVisualization();
                 System.out.println("Checking: " + code[i] + "...");
                 boolean res = av.hasPairedSymbols(code[i]);
                 if (res == true){
                    System.out.println("OK");
                 }
              }catch (PluginException e){
                 System.out.println(e.getMessage());
              }
          }

      }
}

